#include "vdsadapter.h"
#include <qmath.h>

class VdsAdapterPrivate
{
    static int searchTargetIndex(const AdapterData *table, int length, int target);
    static quint64 value(const AdapterData *table, int length, const QString &key);
    static QString key(const AdapterData *table, int length, quint64 value);
    static int index(const AdapterData *table, int length, quint64 value);
    static quint64 normProbleRate(int probleRate);
private:
    static const AdapterData timebaseOffsetTable[]; // 时基档位表
    static const AdapterData voltageScaleTable[]; // 电压档位表
	static const AdapterData currentScaleTable[]; // 电流档位表
    static const AdapterData probleRateTable[]; // 探头倍率表
    static const AdapterData depmemTable[]; // 存储深度表
    static const int m_scaleX = 10; // 脉冲在时基方向所占格数
    static const int m_scaleY = 3; // 脉冲在电压方向所占格数
    static const int m_offsetX = 5; // 脉冲在时基方向偏移格数
    static const int m_offsetY = 0; // 脉冲在电压方向偏移格数
    static const int m_voltageScaleNums = 11; // 固定电压档位数
    static const QString m_depmem; // 存储深度
    static const quint64 m_maxSampleRate = 1000000000; // 最大采样率
    static const quint64 m_sampleRateCeof = 50000000000; // 采样率系数
    friend class VdsAdapter;
};

const QString VdsAdapterPrivate::m_depmem = "1k"; // 存储深度

const AdapterData VdsAdapterPrivate::timebaseOffsetTable[] = {
    { 1, "1.0ns" },
    { 2, "2.0ns" },
    { 5, "5.0ns" },
    { 10, "10ns" },
    { 20, "20ns" },
    { 50, "50ns" },
    { 100, "100ns" },
    { 200, "200ns" },
    { 500, "500ns" },
    { 1000, "1.0us" },
    { 2000, "2.0us" },
    { 5000, "5.0us" },
    { 10000, "10us" },
    { 20000, "20us" },
    { 50000, "50us" },
    { 100000, "100us" },
    { 200000, "200us" },
    { 500000, "500us" },
    { 1000000, "1.0ms" },
    { 2000000, "2.0ms" },
    { 5000000, "5.0ms" },
    { 10000000, "10ms" },
    { 20000000, "20ms" },
    { 50000000, "50ms" },
    { 100000000, "100ms" },
    { 200000000, "200ms" },
    { 500000000, "500ms" },
    { 1000000000, "1.0s" },
    { 2000000000, "2.0s" },
    { 5000000000, "5.0s" },
    { 10000000000, "10s" },
    { 20000000000, "20s" },
    { 50000000000, "50s" },
    { 100000000000, "100s" },
};

const AdapterData VdsAdapterPrivate::voltageScaleTable[] = {
    { 2, "2mv" },
    { 5, "5mv" },
    { 10, "10mv" },
    { 20, "20mv" },
    { 50, "50mv" },
    { 100, "100mv" },
    { 200, "200mv" },
    { 500, "500mv" },
    { 1000, "1v" },
    { 2000, "2v" },
    { 5000, "5v" },
    // ------------
    // 以下档位不存在，仅用于适配显示
    // ------------
    { 10000, "10v" },
    { 20000, "20v" },
    { 50000, "50v" },
    { 100000, "100v" },
    { 200000, "200v" },
    { 500000, "500v" },
    { 1000000, "1000v" },
    { 2000000, "2000v" },
    { 5000000, "5000v" },
};

const AdapterData VdsAdapterPrivate::currentScaleTable[] = {
    { 2, "0.200mA" },
    { 5, "0.500mA" },
    { 10, "1.00mA" },
    { 20, "2.00mA" },
    { 50, "5.00mA" },
    { 100, "10.0mA" },
    { 200, "20.0mA" },
    { 500, "50.0mA" },
    { 1000, "100.0mA" },
    { 2000, "200.0mA" },
    { 5000, "500.0mA" },
    // ------------
    // 以下档位不存在，仅用于适配显示
    // ------------
    { 10000, "1.000A" },
    { 20000, "2.000A" },
    { 50000, "5.000A" },
    { 100000, "10.00A" },
    { 200000, "20.00A" },
    { 500000, "50.00A" },
    { 1000000, "100.0A" },
    { 2000000, "200.0A" },
    { 5000000, "500.0A" },
};

const AdapterData VdsAdapterPrivate::probleRateTable[] = {
    { 1, "x1" },
    { 10, "x10" },
    { 100, "x100" },
    { 1000, "x1000" },
};

const AdapterData VdsAdapterPrivate::depmemTable[] = {
    { 1, "1k" },
    { 10, "10k" },
    { 100, "100k" },
    { 1000, "1M" },
    { 1000, "10M" },
};

/**
 * @brief VdsAdapterPrivate::searchTargetIndex 查找合适的档位
 * @param table 档位表
 * @param length 档位表长度
 * @param target 目标值
 * @return 最合适目标值的档位
 */
int VdsAdapterPrivate::searchTargetIndex(const AdapterData *table, int length, int target) {
    int left = 0, right = length - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (table[mid].value < static_cast<quint64>(target)) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }

    int index = left;
    if (index == length) {
        index = length - 1;
    }

    if (index < 0) {
        index = 0;
    }

    return index;
}

/**
 * @brief VdsAdapterPrivate::value 通过 key 查找 value
 * @param table 档位表
 * @param length 档位表长度
 * @param key 待查找的键
 * @return 键所在的档位：对应的值
 */
quint64 VdsAdapterPrivate::value(const AdapterData *table, int length, const QString &key)
{
    for (int i = 0; i < length; ++i)
    {
        if (table[i].key == key)
        {
            return table[i].value;
        }
    }

    Q_ASSERT(false);
    return 0;
}

/**
 * @brief VdsAdapterPrivate::key 通过 value 查找 key
 * @param table 档位表
 * @param length 档位表长度
 * @param value 待查找的值
 * @return 值所在的档位：对应的键
 */
QString VdsAdapterPrivate::key(const AdapterData *table, int length, quint64 value)
{
    for (int i = 0; i < length; ++i)
    {
        if (table[i].value == value)
        {
            return QString::fromLocal8Bit(table[i].key);
        }
    }

    Q_ASSERT(false);
    return "";
}

/**
 * @brief VdsAdapterPrivate::index 查找 value 对应的档位在档位表中的位置索引
 * @param table 档位表
 * @param length 档位表长度
 * @param value 待查找的值
 * @return 值所在的档位：在档位表中的下标索引
 */
int VdsAdapterPrivate::index(const AdapterData *table, int length, quint64 value)
{
    for (int i = 0; i < length; ++i)
    {
        if (table[i].value == value)
        {
            return i;
        }
    }

    Q_ASSERT(false);
    return -1;
}

/**
 * @brief VdsAdapterPrivate::normProbleRate 归一化探头倍率
 * @param probleRate 探头倍率
 * @return 显示档位与测量档位转换时，使用的探头倍率
 */
quint64 VdsAdapterPrivate::normProbleRate(int probleRate)
{
    int length = sizeof(probleRateTable) / sizeof(probleRateTable[0]);
    for (int i = 0; i < length; ++i)
    {
        if (probleRateTable[i].value == static_cast<quint64>(probleRate))
        {
            return probleRate;
        }
    }

    // 扩展的探头倍率，使用测量档位
    return probleRateTable[0].value;
}

VdsAdapter::VdsAdapter()
{
    d = new VdsAdapterPrivate;
}

VdsAdapter::~VdsAdapter()
{
    delete d;
}

QString VdsAdapter::timebaseScale(int pulseWidth)
{
    int resX = qCeil(pulseWidth * 1000.0 / d->m_scaleX);
    int length = sizeof(d->timebaseOffsetTable) / sizeof(d->timebaseOffsetTable[0]);
    int index = d->searchTargetIndex(d->timebaseOffsetTable, length, resX);
    QString value = d->timebaseOffsetTable[index].key;
    return value;
}

QString VdsAdapter::timebaseOffset()
{
    return QString::number(d->m_offsetX);
}

QString VdsAdapter::voltageScale(int testVoltage, int probeRate)
{
    int resY = qCeil(testVoltage * 1000.0 / probeRate / d->m_scaleY);
    int index = d->searchTargetIndex(d->voltageScaleTable, d->m_voltageScaleNums, resY);
    QString value = d->voltageScaleTable[index].key;
    return value;
}

QString VdsAdapter::voltageOffset()
{
    return QString::number(d->m_offsetY);
}

QString VdsAdapter::triggleLevel(double triggerVoltage, int probeRate, const QString &voltageScale)
{
    int length = sizeof(d->voltageScaleTable) / sizeof(d->voltageScaleTable[0]);
    quint64 value = d->value(d->voltageScaleTable, length, voltageScale);
    double gridNums = triggerVoltage * 1000.0 / probeRate / value;
    return QString::number(gridNums);
}

AdapterTable VdsAdapter::timebaseScaleRange()
{
    AdapterTable table;
    int length = sizeof(d->timebaseOffsetTable) / sizeof(d->timebaseOffsetTable[0]);
    for (int i = 0; i < length; ++i)
    {
        table.append(&(d->timebaseOffsetTable[i]));
    }

    return table;
}

AdapterTable VdsAdapter::voltageScaleMeasureRange()
{
    AdapterTable table;
    for (int i = 0; i < d->m_voltageScaleNums; ++i)
    {
        table.append(&(d->voltageScaleTable[i]));
    }

    return table;
}

AdapterTable VdsAdapter::voltageScaleDisplayRange(int probeRate)
{
    AdapterTable table;
    int length = sizeof(d->voltageScaleTable) / sizeof(d->voltageScaleTable[0]);
    quint64 targetValue = d->voltageScaleTable[0].value * d->normProbleRate(probeRate);
    int startIndex = qMax(d->index(d->voltageScaleTable, length, targetValue), 0);
    int endIndex = qMin(startIndex + d->m_voltageScaleNums, length);
    for (int i = startIndex; i < endIndex; ++i)
    {
        table.append(&(d->voltageScaleTable[i]));
    }
    
    return table;
}

QString VdsAdapter::voltageScaleDisplay2Measure(const QString &voltageScale, int probeRate)
{
    int length = sizeof(d->voltageScaleTable) / sizeof(d->voltageScaleTable[0]);
    quint64 displayVoltageScale = d->value(d->voltageScaleTable, length, voltageScale);
    quint64 measureVoltageScale = displayVoltageScale / d->normProbleRate(probeRate);
    QString value = d->key(d->voltageScaleTable, d->m_voltageScaleNums, measureVoltageScale);
    return value;
}

QString VdsAdapter::voltageScaleMeasure2Display(const QString &voltageScale, int probeRate)
{
    int length = sizeof(d->voltageScaleTable) / sizeof(d->voltageScaleTable[0]);
    quint64 measureVoltageScale = d->value(d->voltageScaleTable, d->m_voltageScaleNums, voltageScale);
    quint64 displayVoltageScale = measureVoltageScale * d->normProbleRate(probeRate);
    QString value = d->key(d->voltageScaleTable, length, displayVoltageScale);
    return value;
}

double VdsAdapter::sampleTime(int pulseWidth)
{
    int resX = qCeil(pulseWidth * 1000.0 / d->m_scaleX);
    int length = sizeof(d->timebaseOffsetTable) / sizeof(d->timebaseOffsetTable[0]);
    int index = d->searchTargetIndex(d->timebaseOffsetTable, length, resX);
    quint64 depmem = d->value(d->depmemTable, sizeof(d->depmemTable) / sizeof(d->depmemTable[0]), d->m_depmem);
    double value = qMin((d->timebaseOffsetTable[index].value * 1.0 / d->m_sampleRateCeof) * depmem, (double)d->m_maxSampleRate) * 10e5;
    return value;
}
